/*******************************************************************************
 * Licensed Materials - Property of IBM
 * (c) Copyright IBM Corporation 2005, 2008. All Rights Reserved. 
 * 
 * Note to U.S. Government Users Restricted Rights:  Use, 
 * duplication or disclosure restricted by GSA ADP Schedule 
 * Contract with IBM Corp.
 *******************************************************************************/

package org.eclipsecon.dui.interpreter.internal;

import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipsecon.dui.swtmodel.MModel;
import org.openarchitectureware.workflow.Workflow;
import org.openarchitectureware.workflow.WorkflowContextDefaultImpl;
import org.openarchitectureware.workflow.ast.util.WorkflowFactory;
import org.openarchitectureware.workflow.issues.Issues;
import org.openarchitectureware.workflow.issues.IssuesImpl;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class ModelContainer {
	private ScrolledComposite fScrolledComposite;
	private Composite fParent;
	private ResourceSet fResourceSet;
	private final ModelContext context;

	/* Last Used Models for Refresh */
	private URI fModelPath;
	private String fBindingPath;
	private String fDataPath;
	private IPath fScript;
	private Target fTarget= Target.SWT;

	public enum Target {
		SWT, HTML
	}

	public ModelContainer(ModelContext context) {
		this.context= context;
	}

	public void setTarget(Target target) {
		fTarget= target;
	}

	public void create(Composite parent) {
		fScrolledComposite= new ScrolledComposite(parent, SWT.H_SCROLL | SWT.V_SCROLL);
		fScrolledComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		fScrolledComposite.setExpandVertical(true);
		fScrolledComposite.setExpandHorizontal(true);
		

		Composite container= new Composite(fScrolledComposite, SWT.None);
		container.setLayout(new GridLayout());
		fScrolledComposite.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_WHITE));
		container.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_WHITE));

		fScrolledComposite.setContent(container);
		fParent= container;
	}

	public IStatus load(URI modelPath, IPath script) {
		fModelPath= modelPath;
		fScript= script;
		fResourceSet= new ResourceSetImpl();
		Resource resource= fResourceSet.createResource(fModelPath);
		try {
			for (Control c : fParent.getChildren()) {
				c.dispose();
			}
			resource.load(Collections.EMPTY_MAP);

			MModel object= (MModel) resource.getContents().get(0);
			if (ResourcesPlugin.getWorkspace().getRoot().getFile(script).exists()) {
				Issues issues= new IssuesImpl();
				Map<String, String> params= new HashMap<String, String>(1);
				String ext= ResourcesPlugin.getWorkspace().getRoot().getFile(script).getLocationURI().toString();
				params.put("file", ext.substring(6, ext.length() - 4));
				Workflow workflow= new WorkflowFactory().parseInitAndCreate(getClass().getClassLoader().getResourceAsStream("org/eclipsecon/dui/interpreter/internal/runScript.oaw"), "runScript.oaw", params, WorkflowFactory.getDefaultConverter(), issues);
				workflow.checkConfiguration(issues);
				if (issues.getErrors().length == 0) {
					WorkflowContextDefaultImpl ctx= new WorkflowContextDefaultImpl();
					ctx.set("model", object);
					workflow.invoke(ctx, null, issues);
					if (issues.getErrors().length != 0) {
						throw new RuntimeException(issues.toString());
					}
				}
			}

			switch (fTarget) {
				case SWT:
					loadForSWT(object);
					break;

				case HTML:
					loadForHTML(object);
					break;
			}

		} catch (Exception e) {
			return Activator.createStatus(e);
		}

		return Status.OK_STATUS;
	}

	private void loadForHTML(MModel object) {
		Browser browser= new Browser(fParent, SWT.NONE);
		browser.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

		StringBuilder builder= new StringBuilder();
		builder.append("<html>");
		builder.append("<body style='overflow: auto; font-family: Tahoma;'>");

		HTMLModelSwitch modelSwitch= new HTMLModelSwitch(null, browser, builder, context);
		modelSwitch.doSwitch(object);

		builder.append("</body>");
		builder.append("</html>");

		browser.setText(builder.toString());
		fParent.layout(true);
		Point point= fParent.computeSize(SWT.DEFAULT, SWT.DEFAULT);
		fParent.setSize(point);
		fScrolledComposite.setMinSize(point);
	}

	private void loadForSWT(MModel object) {
		SWTModelSwitch modelSwitch= new SWTModelSwitch(fParent, context);
		modelSwitch.doSwitch(object);
		fParent.layout(true);
		Point point= fParent.computeSize(SWT.DEFAULT, SWT.DEFAULT);
		fParent.setSize(point);
		fScrolledComposite.setMinSize(point);
	}

	public ResourceSet getResourceSet() {
		return fResourceSet;
	}

	public URI getModelPath() {
		return fModelPath;
	}

	public String getBindingPath() {
		return fBindingPath;
	}

	public String getDataPath() {
		return fDataPath;
	}
	
	public Target getTarget() {
		return fTarget;
	}

	public void setDataPath(String dataPath) {
		fDataPath= dataPath;
	}

	public void setBindingPath(String bindingPath) {
		fBindingPath= bindingPath;
	}

	public ModelContext getContext() {
		return context;
	}

	public IPath getScript() {
		return fScript;
	}
}